﻿using System;
using System.Collections.Generic;
using System.Text;

namespace OmcSocketClient {

    public static class omc {

        /// <summary>
        /// Parse input string to Boolean value.
        /// </summary>
        /// <param name="inputString">Input string</param>
        /// <returns>True if input string representate true value, false otherwise</returns>
        private static Boolean StringToBoolean(string inputString) {
            Boolean result;
            try {
                result = Boolean.Parse(inputString);
            }
            catch {
                result = false;
            }
            return result;
        }

        /// <summary>
        /// Starting new omc process
        /// </summary>
        public static void Start() {
            omcSocketClient.send("START_OMC");
        }

        /// <summary>
        /// Stopping current omc process
        /// </summary>
        public static void Stop() {
            omcSocketClient.send("STOP_OMC");
        }

        /// <summary>
        /// Print omc help.
        /// </summary>
        /// <returns>Omc help</returns>
        public static string Help() {
            return omcSocketClient.send("help()");
        }

        /// <summary>
        /// Print all loaded class definitions.
        /// </summary>
        /// <returns>String classdefs;</returns>
        public static string List() {
            return omcSocketClient.send("list()");
        }

        /// <summary>
        /// Print class definition.
        /// </summary>
        /// <param name="className">TypeName className;</param>
        /// <returns>String classDef;</returns>
        public static string List(string className) {
            return omcSocketClient.send("list(" + className + ")");
        }

        /*      /// <summary>
              /// Load models from file.
              /// </summary>
              /// <param name="fileName">Name of the file, that will be loaded</param>
              /// <returns>True if done succesfully, false otherwise</returns>
              public static Boolean LoadFile(string fileName) {
                  return StringToBoolean(omcSocketClient.send("loadFile(\"" + fileName + "\")"));
              }*/

        /*   /// <summary>
           /// Load the file corresponding to the class, using the Modelica class
           /// name-to-file-name mapping to locate the file.
           /// </summary>
           /// <param name="className">Name of the class, that will be loaded</param>
           /// <returns>True if done succesfully, false otherwise</returns>
           public static Boolean LoadModel(string className) {
               return StringToBoolean(omcSocketClient.send("loadModel(" + className + ")"));
           }*/

        /// <summary>
        /// Save the model className into the file it was loaded from.
        /// </summary>
        /// <param name="className">Name of the model, that may be saved</param>
        public static Boolean Save(string className) {
            return StringToBoolean(omcSocketClient.send("save(" + className + ")"));
        }

        /// <summary>
        /// Light build of modelica code
        /// </summary>
        /// <param name="modelSourceCode">Source code that may be built</param>
        /// <returns>True if done succesfully, false otherwise</returns>
        public static Boolean Build(string modelSourceCode) {
            String result = omcSocketClient.send(modelSourceCode);
            if (result.StartsWith("Ok")) {
                return true;
            }
            else {
                // TODO: Dodelat odchytavani chyb a jejich nahlaseni
                return false;
            }
        }

        /// <summary>
        /// Send API command directly to omc.
        /// Knowledge of OMC API is vital.
        /// </summary>
        /// <param name="inputCommand">OMC API command</param>
        /// <returns>OMC respond on input command</returns>
        public static string Command(string inputCommand) {
            //TODO: Zde budou jiste restrikce, aby nebylo mozno poslat vse
            return omcSocketClient.send(inputCommand);
        }

        /// <summary>
        /// Returns the kind of restricted class of className.
        /// </summary>
        /// <param name="className">Class to be restricted</param>
        /// <returns>Kind of restricted class.</returns>
        public static string GetClassRestriction(string className) {
            return omcSocketClient.send("getClassRestriction(" + className + ")");
        }

        /// <summary>
        /// Returns the the information about the class of className.
        /// </summary>
        /// <param name="className">Class to be restricted</param>
        /// <returns>Information about of restricted class.</returns>
        public static string GetClassInformation(string className) {
            string result = omcSocketClient.send("getClassInformation(" + className + ")");
            if (result == "error\n\r\n") {
                throw new Exception("OMC Error");
            }
            else {
                return result;
            }
        }

        /// <summary>
        /// Returns the names of all class definitions in the global scope.
        /// </summary>
        /// <returns>Names of all class definitions.</returns>
        public static string GetClassNames() {
            return omcSocketClient.send("getClassNames()");
        }

        /// <summary>
        /// Returns the names of all class defintions in a class/package.
        /// </summary>
        /// <param name="className">Class/package specification.</param>
        /// <returns>Names of all class definitions.</returns>
        public static string GetClassNames(string className) {
            return omcSocketClient.send("getClassNames(" + className + ")");
        }

        /// <summary>
        /// Returns the Icon Annotation of the class named by className.
        /// </summary>
        /// <param name="className">Name of class that is queried.</param>
        /// <returns>Icon Annotation.</returns>
        public static string GetIconAnnotation(string className) {
            return omcSocketClient.send("getIconAnnotation(" + className + ")");
        }


        /// <summary>
        /// Returns the nmuber of base classes that class derives from.
        /// </summary>
        /// <param name="className">Name of the class whose number of ancestor should be returned</param>
        /// <returns>Number of the base classes the class derives from. </returns>
        public static int GetInheritanceCount(string className) {
            return Int32.Parse(omcSocketClient.send("getInheritanceCount(" + className + ")"));
        }

        /// <summary>
        /// Returns the base class from which the class derives.
        /// </summary>
        /// <param name="className">Name of the class whose base class sholud be returned</param>
        /// <param name="n">Number of the base class.</param>
        /// <returns>Type of the n-th clas.</returns>
        public static string GetNthInheritedClass(string className, int n) {
            return omcSocketClient.send("getNthInheritedClass(" + className + "," + n.ToString() + ")");
        }

        /// <summary>
        /// Gets number of the components within the class.
        /// </summary>
        /// <param name="className"></param>
        /// <returns></returns>
        public static int GetComponentCount(string className) {
            return Int32.Parse(omcSocketClient.send("getComponentCount(" + className + ")"));
        }

        /// <summary>
        /// Returns information about n-th component of the class.
        /// </summary>
        /// <param name="className">Name of the class whose component will be returned.</param>
        /// <param name="n">Number of the component to return.</param>
        /// <returns>Information about the component - type, name and comment.</returns>
        public static string GetNthComponent(string className, int n) {
            return omcSocketClient.send("getNthComponent(" + className + "," + n.ToString() + ")");
        }

        /// <summary>
        /// Returns annotation with placement of n-th component of the class.
        /// </summary>
        /// <param name="className">Name of the class whose n-th component's annotation will be returned.</param>
        /// <param name="n">Number of the component whose annotation will be returned.</param>
        /// <returns>String with placement annotation</returns>
        public static string GetNthComponentAnnotation(string className, int n) {
            return omcSocketClient.send("getNthComponentAnnotation(" + className + "," + n.ToString() + ")");
        }

        public static string UpdateComponent(string classPlacement) {
            return omcSocketClient.send("updateComponent(" + classPlacement + ")");
        }

        public static string AddClassAnnotation(string updateString) {
            return omcSocketClient.send("addClassAnnotation(" + updateString + ")");
        }

        /*       /// <summary>
               /// Save model to specific file.
               /// </summary>
               /// <param name="fileStr">File to save</param>
               /// <param name="className">Model to save</param>
               /// <returns>True if saved succesfully, false otherwise</returns>
               public static Boolean SaveToSpecificFile(string fileStr, string className) {
                   String result = omcSocketClient.send("setSourceFile(" + className + ",\"" + fileStr + "\")");
                   if (result.StartsWith("Ok")) {
                       return Save(className);
                   }
                   else {
                       return false;
                   }
               }*/

        /// <summary>
        /// Returns list of models saved on server.
        /// </summary>
        /// <returns>List of models.</returns>
        public static List<ServerModelList> GetListOfModelsOnServer() {
            String stringList = omcSocketClient.send("MODEL_LIST");
            List<ServerModelList> ListOfModels = new List<ServerModelList>();
            while (stringList.Length > 2) {
                ServerModelList modelList = new ServerModelList();

                modelList.FileName = stringList.Substring(0, stringList.IndexOf("\n"));
                stringList = stringList.Remove(0, stringList.IndexOf("\n") + 1);

                modelList.RelativeDirectory = stringList.Substring(0, stringList.IndexOf("\n"));
                stringList = stringList.Remove(0, stringList.IndexOf("\n") + 1);

                ListOfModels.Add(modelList);
            }
            return ListOfModels;
        }

        /// <summary>
        /// Load models from file.
        /// </summary>
        /// <param name="fileName">Name of the file, that will be loaded</param>
        /// <param name="fileName">Relative directory of the file, that will be loaded</param>
        /// <returns>True if done succesfully, false otherwise</returns>
        public static Boolean LoadFile(string fileName, string relativeDirectory) {
            return StringToBoolean(omcSocketClient.send("LOAD \"" + fileName + "\"" + relativeDirectory + "\""));
        }

        /// <summary>
        /// Save model to specific file.
        /// </summary>
        /// <param name="fileStr">File to save</param>
        /// <param name="className">Model to save</param>
        /// <returns>True if saved succesfully, false otherwise</returns>
        public static Boolean SaveToSpecificFile(string fileStr, string relativeDirectory, string className) {
            String result = omcSocketClient.send("SAVE_TO_FILE \"" + className + "\"" + fileStr + "\"" + relativeDirectory + "\"");
            if (result.StartsWith("Ok")) {
                return Save(className);
            }
            else {
                return false;
            }
        }

    }

}
